package db

import (
	"fmt"
	"strconv"
	log "github.com/golang/glog"
	"github.com/garyburd/redigo/redis"
)

type User struct {
	Appid  int64
	Uid    int64
	Username  string
	Avatar	  string
	Token	string
}

type UserLoginPoint struct {
	Device_id string
	Platform_id int8
	Login_srv string
	Login_time int64
}

func(user *User) Save(conn redis.Conn) bool {
	//存储用户信息
	key := fmt.Sprintf("%d_%d_userbase", user.Appid, user.Uid)
	_, err := conn.Do("HMSET", key, 
		"appid", fmt.Sprintf("%d", user.Appid), 
		"uid", fmt.Sprintf("%d", user.Uid), 
		"username", user.Username, 
		"avatar", user.Avatar, 
		"token", user.Token,
	)
	if err != nil {
		log.Error("redis HMSET err: user.save", err)
		return false
	}
	
	return true
}

func (user *User) Get(conn redis.Conn, appid int64, uid int64) *User {
	key := fmt.Sprintf("%d_%d_userbase", appid, uid)
	ret, err := redis.Strings(conn.Do("HMGET", key, "appid", "uid", "username", "avatar", "token"))
	if err != nil {
		log.Error("redis HMGET err: user.get", err)
		return nil
	}

	if ret[0] == "" {
		return nil
	}
	
	user.Appid = appid
	user.Uid = uid
	user.Username = ret[2]
	user.Avatar = ret[3]
	user.Token = ret[4]
	
	return user
}

func AddBlack(conn redis.Conn, appid int64, uid int64, bid int64) bool {
	key := fmt.Sprintf("%d_%d_userblacks", appid, uid)
	_, err := conn.Do("SADD", key, bid)
	if err != nil {
		log.Error("redis SADD err: user.addblack", err)
		return false
	}
	
	return true
}

func IsBlack(conn redis.Conn, appid int64, uid int64, bid int64) bool {
	key := fmt.Sprintf("%d_%d_userblacks", appid, uid)
	ret, err := redis.Int(conn.Do("SISMEMBER", key, bid))
	if err != nil {
		log.Error("redis SISMEMBER err: user.isblack", err)
		return false
	}
	
	if ret == 0 {
		return false
	}
	
	return true
}

func GetBlacks(conn redis.Conn, appid int64, uid int64) []int {
	key := fmt.Sprintf("%d_%d_userblacks", appid, uid)
	ret, err := redis.Ints(conn.Do("SMEMBERS", key))
	if err != nil {
		log.Error("redis SMEMBERS err: user.getblacks", err)
		return nil
	}
	
	return ret
}

func RemoveBlack(conn redis.Conn, appid int64, uid int64, bid int64) bool {
	key := fmt.Sprintf("%d_%d_userblacks", appid, uid)
	_, err := redis.Int(conn.Do("SREM", key, bid))
	if err != nil {
		log.Error("redis SREM err: user.removeblack", err)
		return false
	}
	
	return true
}

func AddGroup(conn redis.Conn, appid int64, uid int64, gid int64) bool {
	key := fmt.Sprintf("%d_%d_usergroups", appid, uid)
	_, err := conn.Do("SADD", key, gid)
	if err != nil {
		log.Error("redis SADD err: user.addgroup", err)
		return false
	}
	
	return true
}

func RemoveGroup(conn redis.Conn, appid int64, uid int64, gid int64) bool {
	key := fmt.Sprintf("%d_%d_usergroups", appid, uid)
	_, err := redis.Int(conn.Do("SREM", key, gid))
	if err != nil {
		log.Error("redis SREM err: group.removegroup", err)
		return false
	}
	
	return true
}

func GetGroups(conn redis.Conn, appid int64, uid int64) []int {
	key := fmt.Sprintf("%d_%d_usergroups", appid, uid)
	
	ret, err := redis.Ints(conn.Do("SMEMBERS", key))
	if err != nil {
		log.Error("redis SMEMBERS err: user.getgroups", err)
		return nil
	}
	
	return ret
}

func GetLoginPoints(conn redis.Conn, appid int64, uid int64) []string {
	key := fmt.Sprintf("%d_%d_loginpoints", appid, uid)
	ret, err := redis.Strings(conn.Do("SMEMBERS", key))
	if err != nil {
		log.Error("redis SMEMBERS err: user.getloginpoints", err)
		return nil
	}
	
	return ret
}

func AddLoginPoints(conn redis.Conn, appid int64, uid int64, device_id string) bool {
	key := fmt.Sprintf("%d_%d_loginpoints", appid, uid)
	_, err := conn.Do("SADD", key, device_id)
	if err != nil {
		log.Error("redis SADD err: user.addloginpoints", err)
		return false
	}
	
	return true
}

func GetLoginPoint(conn redis.Conn, appid int64, uid int64, device_id string) *UserLoginPoint {
	key := fmt.Sprintf("%d_%d_loginpoint_%s", appid, uid, device_id)
	values, err := redis.Strings(conn.Do("HMGET", key, "device_id", "platform_id", "login_srv", "login_time"))
	if err != nil {
		log.Error("redis HMGET err: user.getloginpoint", err)
		return nil
	}
	
	platform_id, _ := strconv.Atoi(values[1]);
	login_time, _ := strconv.Atoi(values[3]);
	
	point := &UserLoginPoint{
		Device_id : values[0],
		Platform_id : int8(platform_id),
		Login_srv : values[2],
		Login_time : int64(login_time),
	}
	
	return point
}

func SetLoginPoint(conn redis.Conn, appid int64, uid int64, point *UserLoginPoint) bool {
	key := fmt.Sprintf("%d_%d_loginpoint_%s", appid, uid, point.Device_id)
	_, err := conn.Do("HMSET", key, 
		"device_id", point.Device_id, 
		"platform_id", fmt.Sprintf("%d", point.Platform_id), 
		"login_srv", point.Login_srv, 
		"login_time", fmt.Sprintf("%d", point.Login_time),
	)
	if err != nil {
		log.Error("redis HMSET err: user.setloginpoint", err)
		return false
	}
	
	return true
}

func RemoveLoginPoint(conn redis.Conn, appid int64, uid int64, device_id string) bool {
	key := fmt.Sprintf("%d_%d_loginpoints", appid, uid)
	_, err := conn.Do("SREM", key, device_id)
	if err != nil {
		log.Error("redis SREM err: user.removeloginpoint", err)
		return false
	}
	
	key = fmt.Sprintf("%d_%d_loginpoint_%s", appid, uid, device_id)
	_, err = conn.Do("DEL", key)
	if err != nil {
		log.Error("redis DEL err: user.removeloginpoint", err)
		return false
	}
	
	return true
}

func AddRoom(conn redis.Conn, appid int64, uid int64, rid int64) bool {
	key := fmt.Sprintf("%d_%d_userrooms", appid, uid)
	_, err := conn.Do("SADD", key, rid)
	if err != nil {
		log.Error("redis SADD err: user.addroom", err)
		return false
	}
	
	return true
}

func RemoveUserRoom(conn redis.Conn, appid int64, uid int64, rid int64) bool {
	key := fmt.Sprintf("%d_%d_userrooms", appid, uid)
	_, err := redis.Int(conn.Do("SREM", key, rid))
	if err != nil {
		log.Error("redis SREM err: group.removeroom", err)
		return false
	}
	
	return true
}

func GetRooms(conn redis.Conn, appid int64, uid int64) []int {
	key := fmt.Sprintf("%d_%d_userrooms", appid, uid)
	
	ret, err := redis.Ints(conn.Do("SMEMBERS", key))
	if err != nil {
		log.Error("redis SMEMBERS err: user.getrooms", err)
		return nil
	}
	
	return ret
}

//用户好友相关
func AddFriend(conn redis.Conn, appid int64, uid int64, fid int64) bool {
	user := new(User)
	u := user.Get(conn, appid, fid)
	if u == nil {
		return false
	}
	
	key := fmt.Sprintf("%d_%d_userfriends", appid, uid)
	_, err := conn.Do("SADD", key, fid)
	if err != nil {
		log.Error("redis SADD err: user.addfriend", err)
		return false
	}
	
	return true
}

func RemoveFriend(conn redis.Conn, appid int64, uid int64, fid int64) bool {
	key := fmt.Sprintf("%d_%d_userfriends", appid, uid)
	_, err := redis.Int(conn.Do("SREM", key, fid))
	if err != nil {
		log.Error("redis SREM err: group.removefriend", err)
		return false
	}
	
	return true
}

func GetFriends(conn redis.Conn, appid int64, uid int64) []int {
	key := fmt.Sprintf("%d_%d_userfriends", appid, uid)
	
	ret, err := redis.Ints(conn.Do("SMEMBERS", key))
	if err != nil {
		log.Error("redis SMEMBERS err: user.getfriends", err)
		return nil
	}
	
	return ret
}